from functools import wraps
from itsdangerous import TimedJSONWebSignatureSerializer as TJWSS, SignatureExpired, BadData
from django.core.cache import cache

from utils.cache_operation import CacheHandle
from utils.enums import SCE
from utils.result import R

salt = "zfhjskhxyxphcmy"
tjwss_30 = TJWSS(salt, 60 * 60 * 24 * 30)


def illegal_token(reason):
    return R.error(SCE.illegal_token, f'登录状态异常，请重新登陆，（异常原因：{reason}）').data()


# 若验证成功，根据用户名，密码，身份返回一个token
def make_token(user_id: int, username: str, password: str) -> str:
    payload = {
        'id': user_id,
        'username': username,
        'password': password
    }
    token = tjwss_30.dumps(payload).decode()

    return token


# 校验token函数装饰器版
def verify_token():
    def decorator(func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            # args是从外部传来的信息   请求头中的信息都放在META中，去读方法自己搜索
            token = args[0].META.get("HTTP_TOKEN")
            try:
                # 验证token携带的账号密码是否和登记相符
                temp = tjwss_30.loads(token)
            except SignatureExpired:  # 超时
                CacheHandle('user').delete_dict()
                return illegal_token('登录凭证过期')
            except BadData:  # 非法
                return illegal_token('登录凭证损坏')
            except TypeError:  # 无token，获取结果为None
                return illegal_token('无登录凭证')

            user_id = temp['id']
            username = temp['username']
            password = temp['password']

            # 验证该用户是否已经被禁止登入，如果是的话就直接要求其重新登录
            try:
                user_cache = cache.get('user')[user_id]
                if user_cache['username'] != username or user_cache['password'] != password:
                    return illegal_token('无登录凭证')
            except KeyError:
                return illegal_token('无登录凭证')
            kwargs['user_id'] = user_id
            return func(*args, **kwargs)
        return wrapped_function
    return decorator
